#pragma once

#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include <functional>
#include "Log.hpp"
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace std;
static const int defaultnum=5;
class ThreadData
{
public:
    ThreadData(const string &name):threadname(name)
    {}
    ~ThreadData()
    {}
    string threadname;
};

template <class T>
class ThreadPool
{
public:
    static ThreadPool<T>* GetInstance()
    {
        if(instance==nullptr)//这个instance是做什么的的？
        {
            LockGuard lockguard(&sig_lock);//初始化锁，只需要一个？
            if(instance==nullptr)
            {
                lg.LogMessage(Info,"创建单例成功...\n");
                instance =new ThreadPool<T> ();
            }

        }
        return instance;
    }
    bool Start()
    {
        for(auto &thread:_threads)
        {
            thread.Start();
            lg.LogMessage(Info,"%s is running...\n",thread.ThreadName().c_str());
        }
        return true;
    }
    void ThreadWait(const ThreadData &td)//每个线程都需要调用，循环调用吧应该是
    {
        lg.LogMessage(Debug,"no task ,%s is sleeping...\n",td.threadname.c_str());
        pthread_cond_wait(&_cond,&_mutex);//这个函数
    }
    void checkSelf()
    {

    }
    void ThreadRun(ThreadData &td)
    {
        while(true)
        {
            //在运行之前，可以先查看是否符合要求
            T t;
            {
                LockGuard lockguard(&_mutex);
                while(_q.empty())
                {
                    ThreadWait(td);
                    lg.LogMessage(Debug,"thread %s is waker\n",td.threadname.c_str());
                }
                t=_q.front();//我们刚刚的问题是没有给他赋值直接运行。   
                _q.pop();
            }
            t();
        }
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void Push(T &in)
    {
        LockGuard lockguard(&_mutex);
        _q.push(in);
        ThreadWakeup();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void Wait()
    {
        for(auto &thread:_threads)
        {
            thread.Join();
        }
    }
private:
//单例模式
    ThreadPool(int thread_num=defaultnum):_thread_num(thread_num)
    {
        pthread_mutex_init(&_mutex,nullptr);//锁，初始化，然后直接传过去用
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<_thread_num;i++)
        {
            string threadname="thread-";
            threadname +=to_string(i+1);
            ThreadData td(threadname);//初始化名字

            //两种方法推送
            // ThreadData td(threadname);
            // Thread<ThreadData> t(threadname,bind(&ThreadPool<T>::ThreadRun,this,placeholders::1),td);
            // _threads.push_back(td);//入队列
            //第二种方法
            _threads.emplace_back(threadname,bind(&ThreadPool::ThreadRun,this,placeholders::_1),td);//placeholders这是占位符
            lg.LogMessage(Info,"%s is create ...\n",threadname.c_str());

        }
    }
    ThreadPool(const ThreadPool<T> &tp)=delete;
    const ThreadPool<T> operator=(const ThreadPool<T> &tp)=delete;
    queue<T> _q;//运行队列
    vector<Thread<ThreadData>> _threads;//疑问
    int _thread_num;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    static ThreadPool<T> *instance;
    static pthread_mutex_t sig_lock;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance =nullptr;//只创建一个对象
template <class T>
pthread_mutex_t ThreadPool<T>::sig_lock=PTHREAD_MUTEX_INITIALIZER;
